package org.rectask.view;

import java.util.ArrayList;

import org.rectask.model.*;

public class ColorCalculator {
    // Hack to test functionality
    static int WHITE = 0;
    static int BLACK = 10;
    static int BLUE = 20;
    static int GREEN = 30;
    static int YELLOW = 40;
    static int RED = 50;
    
    /**
     * Calculate the color for each date in the range, given 
     * a task, and return it as an ArrayList.
     * 
     * @param task The task for which to calculate the colors
     * @param startDate The first date on which to calculate the color
     * @param endDate The final date on which to calculate the color
     * 
     * @return a list of colors, the first one corresponding to the color
     * of the first date, and so on. 
     */
    public ArrayList<Integer> calculateColors(Task task, Date startDate, Date endDate) {
	ArrayList<Integer> result = new ArrayList<Integer>();
	int minPeriod = task.getMinPeriod();
	int maxPeriod = task.getMaxPeriod();

	// Find first color
	Date lastExecutionDate = task.getLastExecutionDateBefore(startDate);
	int currentDistance;
	if (lastExecutionDate == null)
	    currentDistance = -1;
	else 
	    currentDistance = lastExecutionDate.daysUntil(startDate);
	int firstColor = getColor(currentDistance, minPeriod, maxPeriod);
	result.add(firstColor);
	
	// Find all the other colors
	ArrayList<Date> executionDates = task.getExecutionDates();
	Date currentDate = new Date(startDate);
	while (currentDate.before(endDate)) {
	    currentDate.addDays(1);
	    
	    if (currentDistance >= 0) // Negative distance means no task has ever 
		currentDistance++;    // been executed, so no need for updating this
	    
	    if (executionDates.contains(currentDate)) {
		result.add(BLACK);
		currentDistance = 0;
	    } else {
		result.add(getColor(currentDistance, minPeriod, maxPeriod));
	    }
	}
	return result;
    }

    /**
     * Returns the color for the current date, given its distance to 
     * the last execution of the task, the minimum periodicity and 
     * the maximum periodicity. 
     * 
     * If the distance is negative, WHITE is returned.
     * 
     * @param distance
     * @param minPeriod
     * @param maxPeriod
     * @return
     */
    private int getColor(int distance, int minPeriod, int maxPeriod) {
	if (distance < 0)
	    return WHITE;
	else if (distance == 0)
	    return BLACK;
	else if (distance < minPeriod)
	    return BLUE;
	else if (distance < maxPeriod)
	    return GREEN;
	else if (distance == maxPeriod)
	    return YELLOW;
	else
	    return RED;
    }
    
    /**
     * For testing
     * 
     * @param args
     */
    public static void main(String[] args) {	
	Date startDate = new Date(1,1,2009);
	Date endDate = new Date(14,1,2009);

	int minPeriod = 2;
	int maxPeriod = 5;
	if (args.length == 2) {
	    minPeriod = Integer.parseInt(args[0]);
	    maxPeriod = Integer.parseInt(args[1]);
	}
	
	Task task = new Task("New task", startDate, minPeriod, maxPeriod);
	task.addExecutionDate(new Date(3,1,2009));
	task.addExecutionDate(new Date(6,1,2009));
	task.addExecutionDate(new Date(13,1,2009));
	task.addExecutionDate(new Date(13,1,2009));
	task.addExecutionDate(new Date(3,12,2008));

	ColorCalculator cc = new ColorCalculator();
	ArrayList<Integer> colors = cc.calculateColors(task, startDate, endDate);
	System.out.println("Min:" + minPeriod + "  Max:" + maxPeriod);
	System.out.println(colors);
	System.out.println(task.toXML());
    }
}
